import {observable, action, computed, runInAction} from 'mobx'

/**
 * 基于mobx动画效果
 */
export class Animate {
    /**
     * 当前生效的样式,请配和classnames组件使用,将属性绑定到需要动画的组件上
     */
    @observable _classNames = []

    @observable styles = {}

    _enterTimeout = null

    _leaveTimeout = null

    constructor(animateName) {
        if (!animateName) {
            throw new Error('new Animate(animateName),parameter animateName can not be null')
        }
        this._animateName = animateName
    }

    @computed get classNames() {
        return this._classNames.join(' ')
    }

    @action setStyles(styles) {
        this.styles = styles
    }

    /**
     * 进入动画
     * @param timeout 动画延时
     */
    @action enter(timeout = 200, callback = null) {
        let classNames = []
        classNames.push(`animating`)
        classNames.push(`${this._animateName}-enter`)
        classNames.push(`animating-enter-active`)
        classNames.push(`${this._animateName}-enter-active`)
        this._classNames = classNames
        this._enterTimeout = setTimeout(() => {
            runInAction(() => {
                this._classNames = ['animate-actived']
                callback && callback()
            })
        }, timeout)
    }

    /**
     * 离开动画
     * @param timeout
     * @param callback
     */
    @action leave(timeout = 200, callback) {
        let classNames = []
        classNames.push(`animate-actived`)
        classNames.push(`animating`)
        classNames.push(`${this._animateName}-leave`)
        classNames.push(`animating-leave-active`)
        classNames.push(`${this._animateName}-leave-active`)
        this._classNames = classNames
        this._leaveTimeout && clearTimeout(this._leaveTimeout)
        this._enterTimeout && clearTimeout(this._enterTimeout)
        this._leaveTimeout = setTimeout(() => {
            runInAction(() => {
                this._classNames = []
                callback && callback()
            })
        }, timeout)
    }

    /**
     * 离开动画异步
     * @param timeout
     * @returns {Promise<any>}
     */
    @action leaveAsync(timeout = 200) {
        return new Promise(resolve => {
            this.leave(timeout, () => {
                resolve()
            })
        })
    }
}